/**
 * 
 */
package com.chen.invoicing;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.swift.cfg4u.instance.ConstInstance;
import org.swift.cfg4u.servlet.ConfigController;
import org.swift.util.http.WebClient;

import com.google.gson.Gson;

import entity.Card;
import entity.CardBatch;
import entity.GoodsProduct;
import entity.JifenProduct;
import entity.OrderInfo;
import entity.TableExpand;
import interfaces.JifenNotifyInterface;
import jifen.cmbc.invoicing.entity.DeliverGoodsDetail;
import jifen.cmbc.invoicing.entity.ResVitualOrderListQueryDTO;
import jifen.cmbc.invoicing.entity.VirtualCodeInfo;
import jifen.ordercard.JifenCardOrderInfoResponse;
import net.sf.json.JSONObject;
import service.CardService;
import service.JifenService;
import service.OrderInfoService;
import service.RedisService;
import service.TableExpandService;
import util.EncryptUtil;
import util.HttpUtils;
import util.MailUtil;

/**
 * 
 *
 *@类名称：JifenBusinessApi.java
 *@类描述：民生电商进销存对接相关方法
 *@创建人：zhongy
 *@创建时间：2017年7月2日-上午9:13:58
 *@修改备注:
 *@version
 */
public class JifenBusinessApi implements JifenNotifyInterface {


	private static Gson gsonUtil = new Gson();
	private static String CODE = "cmbc_invoicing_params";
	static SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
	static Logger log = Logger.getLogger(JifenBusinessApi.class);
	private static final String logPre="民生(进销存):";
	/**
	 * 
	 * 一期主要商品录入流程： TODO 这边待确定
	 *  setp1、贵方开通相关供应商后台 
	 *  setp2、我方商务人员登录进行相关产品的录入 
	 *  
	 *  主要订单流程：
	 *  step1、用户在贵方系统下单 
	 *  step2、微能调用‘虚拟订单列表信息查询 ’ 查询 ‘待发货的订单’ 
	 *  step3、微能对‘待发货的订单’ 进行发货处理 
	 *  step4、微能调用 ‘虚拟订单发货API ’ 通知贵方
	 *   
	 *  主要退款流程： 
	 *  step1、用户在贵方平台发起退款(是否存在部分退款？)
	 *  step2、贵方和我方商务确定以后进行退款
	 * 
	 * 
	 * 
	 * 
	 *
	 */
	
	public static String readFileByLines(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            StringBuilder sb = new StringBuilder();
            int line = 1;
            // 一次读入一行，直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                // 显示行号
            	sb.append(tempString);
                line++;
            }
            reader.close();
            return sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
        return "";
    }
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) throws Exception {
		ConfigController.start();
	//	query( "",new Date());
	//	push("41564564", new ArrayList<VirtualCodeInfo>());
		
		// JifenBusinessApi api=new JifenBusinessApi();
		//
		// api.orderStateNotify(OrderInfoService.getOrderInfo("2016111930293714"));
		// query();
		// test();
		process();
//		Date curr = new Date();
//		Calendar time = Calendar.getInstance();
//		time.setTime(curr);
//		time.add(Calendar.DATE, 60);
//		System.out.println(time.getTime());
//		OrderInfo info =OrderInfoService.getOrderInfo(21563);
//		new JifenBusinessApi().orderStateNotify(info);
		
		System.exit(0);
	}



	

	/*
	 * 处理查询返回的订单报文
	 */
	public static void process() {
		/**
		 * step1、调用查询接口进行查询
		 * step2、业务参数检查
		 * step3、参数解析
		 * step4、业务处理
		 * 
		 * 
		 * 
		 * 
		 */
		//step1、调用查询接口进行查询
		String resp = null;
		try {
			resp = query( "",new Date());
			log.info(logPre+"【process】 查询待处理订单："+resp);
			resp = JifenBusinessApi.readFileByLines("E:\\test.txt");
		} catch (Exception e2) {
			log.info(logPre+"【process】查询接口异常：Exception：" + e2.getMessage());
			return;
		}
		//step2、业务参数检查
		if (!StringUtils.isEmpty(resp)) {
			// 校验是否配置了采购商产品
			String jifenProductId = ConstInstance.getValuedByKeyd(CODE,"jifenProductId");
			if (StringUtils.isEmpty(jifenProductId)) {
				log.info(logPre+"【process】未配置常量参数：jifenProductId ");
				return;
			}
			JifenProduct jp = null;
			try {
				jp = JifenService.getJifenProduct(Long.valueOf(jifenProductId));
				if (jp == null) {
					log.info(logPre+"【process】该采购商产品不存在，jifenProductId：" + jifenProductId);
					return;
				}
			} catch (Exception e1) {
				log.info(logPre+"【process】查询采购商产品异常； Exception:" + e1.getMessage());
				return;
			}
			// step3、参数解析
			ResVitualOrderListQueryDTO dto = gsonUtil.fromJson(resp,ResVitualOrderListQueryDTO.class);
			if(dto==null||ResVitualOrderListQueryDTO.STATUS_SUCCESS!=dto.getStatus() ){//状态判断
				log.info(logPre+"【process】此次查询返回值转化异常 ");
				return;
			}
			List<jifen.cmbc.invoicing.entity.OrderInfo> list=dto.getData();
			if (list==null || list.size()<1) {//数据判断
				log.info(logPre+"【process】此次查询没有待发货的订单 ");
				return;
			}
			//step4、业务处理
			int successCount=0;
			for (jifen.cmbc.invoicing.entity.OrderInfo orderInfo : list) {
				// 校验我方是否已经存在该订单
				OrderInfo or = null;
				try {
					//apOrderId=DeliverGoodsId 已确定
					//FIXME 订单存在判断,有失败的客服处理
					String apOrderId=orderInfo.getDeliverGoodsId();//XXX  该字段的值请勿修改（重复订单的唯一标识）
					or = OrderInfoService.getOrderInfoByApOrderNoAndJifenBusinessId(apOrderId,jp.getJifenBusinessId());
					if (or != null) {
						log.info(logPre+"【process】该订单已经处理。第三方订单号：" + or.getApOrderId()+ ",orderId=" + or.getOrderId());
						//时间判断
						long curr = System.currentTimeMillis();
						long logTime = or.getLogTime().getTime();
						long costTime = curr - logTime;
						String timeout = ConstInstance.getValuedByKeyd(CODE, "invoicing_timeout");
						timeout = StringUtils.isBlank(timeout)?"43200000":timeout;//43200000 12小时
						if(Long.parseLong(timeout) <= costTime){
							warnTimeOut(or.getOrderId());
						}
						continue;
					}
				} catch (Exception e) {
					log.info(logPre+"【process】查询订单异常，Exception：" + e.getMessage());
					continue;
				}
				//这边是否还需要进行状态判断对方侧 目前还没有的  只有获取未发货的发货单的接口
				String rechargeAccount = orderInfo.getRechargeAccount();//XXX 这个字段是否一定会传递
				if(StringUtils.isBlank(rechargeAccount)){
					//FIXME 从OSM同步给SCM,SCM再同步给我们,只要OSM有同步，SCM就会有
					continue;
				}
				
				if(orderInfo.getDeliverItem() == null){
					//XXX 肯定会有
					continue;
				}
				
				// 生成订单
				boolean b = saveOrderInfo(orderInfo, orderInfo.getDeliverItem().get(0), jp);// 此处商品列表只有一个值，确定过
				if (!b) {
					continue;
				}else{
					successCount++;
				}
				
			}
			log.info(logPre + "【process】共计："+list.size() +"笔,处理成功："+successCount);
		}

	}

	@Override
	public boolean orderStateNotify(OrderInfo info) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		String timeStr = df.format(new Date());
		List<VirtualCodeInfo> virtualCodeInfos = new ArrayList<VirtualCodeInfo>();
		List<Card> cards;
		try {
			/**
			 * step1、调用接口进行通知
			 * step2、删除队列
			 * 
			 * 
			 */
			
			// 首先查询是否已同步
			String apOrderId = info.getApOrderId();
//			String query = query( "",info.getLogTime());
//			if (!StringUtils.isBlank(query)) {
//				ResVitualOrderListQueryDTO dto = gsonUtil.fromJson(query,ResVitualOrderListQueryDTO.class);
//				if (dto.getTotalResults() > 0) {
//					jifen.cmbc.entity.OrderInfo orderInfo = dto.getOrderInfos()
//							.get(0);
//					if ("2".equals(orderInfo.getOrderStatus()) ) {//重复订单直接返回成功
//						log.info("【orderStateNotify】info :"+info.getOrderId()+"重复通知");
//						return true;
//					}
//
//				}
//			}
			cards = CardService.getCardListByOrderId(info.getOrderId());
			if (cards == null || cards.size() == 0) {
				// 没有卡券的情况下，将我方订单号作为卡号
				int count=info.getGoodsProductNum();
				for(int i=0 ;i<count;i++){
					VirtualCodeInfo v = new VirtualCodeInfo();
					v.setBeginTime(timeStr + " 00:00:00");
					v.setEndTime(timeStr + " 23:59:59"	);
					v.setVirtualCode(info.getOrderId()+"_"+i);
					v.setVirtualPwd(info.getOrderId()+"_"+i);
					//XXX 这边需要使用拓展表的数据来进行通知
					v.setSkuId(getCmbcPSN(info));
					virtualCodeInfos.add(v);
				}	
			} else {
				for (Card card : cards) {
					VirtualCodeInfo v = new VirtualCodeInfo();
					v.setBeginTime(timeStr + " 00:00:00");
					v.setEndTime(timeStr + " 23:59:59"	);
					v.setVirtualCode(card.getCard_number());
					v.setVirtualPwd(card.getCard_number());
					v.setSkuId(getCmbcPSN(info));
					virtualCodeInfos.add(v);
				}
			}
			String post=push(apOrderId, virtualCodeInfos);
			if (!StringUtils.isBlank(post)) {
				JSONObject ticketJson = JSONObject.fromObject(post);
				if (ResVitualOrderListQueryDTO.STATUS_SUCCESS.equals(ticketJson.getInt("Status"))) {
					return true;
				}
			}
		} catch (Exception e) {
			log.error( logPre + "【orderStateNotify】 下单通知异常", e);
			return false;
		}
		return false;
	}

	@Override
	public boolean cardUseNotify(Card card) {
		return false;
	}

	@Override
	public boolean cardCancelNotify(Card card) {
		return false;
	}

	

	// ------------------------------------------------------相关工具方法------------------------------------------------------------------------
	// 保存WN订单
	public static boolean saveOrderInfo(jifen.cmbc.invoicing.entity.OrderInfo or,DeliverGoodsDetail detail, JifenProduct jp) {
		String batchNo = ConstInstance.getValuedByKeyd(CODE,detail.getSkuId());// 常量中获取对应的批次号
		if (StringUtils.isBlank(batchNo)) {
			log.info(logPre+"【process】未配置常量参数，产品对应批次: " + detail.getSkuId());
			warn(detail.getSkuId());
			return false;
		}
		CardBatch cb = null;
		try {			
			cb = CardService.getCardBatch(batchNo);
			if (cb == null) {
				log.info(logPre + "【process】该批次不存在，batchNo：" + batchNo);
				return false;
			}
		} catch (Exception e) {
			log.info(logPre + "【process】查询批次异常，Exception:" + e.getMessage());
			return false;
		}
		GoodsProduct gp = null;
		try {
			gp = cb.getGoodsProduct();
			if (gp == null) {
				log.info(logPre + "【process】该供应商产品不存在，batchNo：" + batchNo);
				return false;
			}
		} catch (Exception e) {
			log.info(logPre + "【process】查询供应商产品异常，Exception:" + e.getMessage());
			return false;
		}

		String orderid = or.getDeliverGoodsId();
		try {
			//调用订购接口
			String customerNo = or.getRechargeAccount();
			JifenCardOrderInfoResponse resp = OrderInfoService.orderByApiCardBatchs(jp, cb, null,
					customerNo, detail.getDeliverQuantity() + "", orderid);
			if(!"0000".equals(resp.getRetResult())){
				log.info(logPre + "【process】orderByApiCardBatchs失败:" + resp);
				return false;
			}
			
			String wnOrderId = resp.getWnOrderId();
			OrderInfoService.updateOrderInfoExt4(wnOrderId, or.getOrderCode());
			
			//FIXME 保存对应产品编号
			try{
				TableExpand te=new TableExpand();
				OrderInfo orderInfo = OrderInfoService.getOrderInfoByApOrderNo(orderid);
				te.setLinkedId(orderInfo.getId());//订单的orderId
				te.setTableName("order_info");
				te.setTableColumn("cmbc_productSn");
				te.setTableValue(or.getDeliverItem().get(0).getSkuId());//SkuId
				TableExpandService.saveTableExpand(te, null);
			}catch(Exception e){
				log.info(logPre + "【process】对应关系保存失败，Exception:"+orderid + e.getMessage());
			}
			
			
		} catch (Exception e) {
			log.info(logPre + "【process】订单保存异常，Exception:"+orderid + e.getMessage());
			return false;
		}
		
		return true;
	}

	
	
	
	
	//获取对应的产品编号
	public static String getCmbcPSN(OrderInfo info){//XXX
		TableExpand te=TableExpandService.getByLinkedIdAndTableNameAndColumn(info.getId(), "order_info", "cmbc_productSn");
		String productSn=(te==null?ConstInstance.getKeydByValued(CODE, ""+info.getBatchId()):te.getTableValue());
		return productSn;
	} 
	
	
	//获取时间相关方法
	public static String getDayStr(Date date,int diff,String str){
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		Calendar rightNow = Calendar.getInstance();
		rightNow.setTime(date);
		rightNow.add(Calendar.DAY_OF_YEAR, diff);
		Date d=rightNow.getTime();
		String ret = sdf.format(d);;
		return ret+" "+str;
	}
	
	//产品未配置进行报警
	public static void warn(String productSn){
		//设置报警间隔
		String a=RedisService.get("cmbc_invoicing_warn_"+productSn);
		if(!StringUtils.isBlank(a)){//已经有了不报警
			return ;
		}
		
		try{
			Integer seconds= Integer.valueOf(ConstInstance.getValuedByKeyd(CODE, "cmbc_invoicing_warn_interval"));
			RedisService.setAndexpire("cmbc_invoicing_warn_"+productSn, productSn, seconds);
			//获取对应的报警邮箱
			String content="民生进销存产品编号未配置:"+productSn;
			String[] emailAddr = ConstInstance.getValuedByKeyd(CODE, "cmbc_invoicing_emails").split(",");
			MailUtil.send("民生进销存业务报警(1小时一次)", content, emailAddr);
		}catch(Exception e){
			log.info(logPre + "【process】报警失败"+productSn+e.getMessage());
		}

	}
	
	public static void warnTimeOut(String orderId){
		//设置报警间隔
		String a=RedisService.get("cmbc_invoicing_timeout_warn_"+orderId);
		if(!StringUtils.isBlank(a)){//已经有了不报警
			return ;
		}
		
		try{
			Integer seconds= Integer.valueOf(ConstInstance.getValuedByKeyd(CODE, "cmbc_invoicing_warn_interval"));
			RedisService.setAndexpire("cmbc_invoicing_timeout_warn_"+orderId, orderId, seconds);
			//获取对应的报警邮箱
			String content="民生进销存订单处理时间超时:"+orderId;
			String[] emailAddr = ConstInstance.getValuedByKeyd(CODE, "cmbc_invoicing_emails").split(",");
			MailUtil.send("民生进销存订单处理时间超时(1小时一次)", content, emailAddr);
		}catch(Exception e){
			log.info(logPre + "【process】报警失败"+orderId+e.getMessage());
		}

	}
	
	// 查询
	public static String query(String userNumber,Date date) throws Exception {
			// 查询对应需要发货的相关商品
		Map params = getQueryMsg(userNumber, "13",date);
		String queryUrl=ConstInstance.getValuedByKeyd(CODE,"queryUrl");
		queryUrl=queryUrl+"?"+HttpUtils.map2StringObjectValue(params);
		log.info(logPre+"查询请求-"+queryUrl);
		String resp=WebClient.retrieveWebContent(queryUrl);
		log.info(logPre+"查询返回-"+resp);
		return resp;
	}
	// 推送
	public static String push(String apOrderId, List<VirtualCodeInfo> cards) throws Exception {
			// 查询对应需要发货的相关商品
		Map params = getPushMsg(apOrderId, cards);//getQueryMsg(userNumber, "13",date);
		String deliveryUrl=ConstInstance.getValuedByKeyd(CODE,"deliveryUrl");
		log.info(logPre+"发货请求-"+deliveryUrl+",params=" + params);
		String resp=WebClient.post(deliveryUrl, params);
		log.info(logPre+"发货返回-"+resp);
		return resp;
	}
	
	// -------------------------------------------------------相关报文组装区---------------------------------------------------
		// 发货通知报文
	private static Map<String, Object> getPushMsg(String orderId,List<VirtualCodeInfo> cards) throws Exception {
			Map<String, Object> form = new HashMap<String, Object>();
			form.put("method", "virtualorderdelivery");// 处理方法
			Date date = new Date();
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			String timestamp = df.format(date);
			form.put("timestamp", timestamp);
			form.put("appkey", ConstInstance.getValuedByKeyd(CODE,"appKey"));
			form.put("v", "1.0");
			// 接口特殊参数
			form.put("VendorId", ConstInstance.getValuedByKeyd(CODE,"vendorId"));// 供应商id
			form.put("DeliverGoodsId", orderId);// 供应商id
			form.put("VirtualCodeList", gsonUtil.toJson(cards));
			String key=ConstInstance.getValuedByKeyd(CODE,"appSecret");
			String signStr=(key+EncryptUtil.getOrderByLetter(form)+key).trim();
			String sign = EncryptUtil.SHA1(signStr, "UTF-8");	
			form.put("sign", sign);
			return form;
		}

		// 查询报文
	private static Map<String, Object> getQueryMsg(String userNumber, String orderType,Date dateStart)throws Exception {
			
			Map<String, Object> form = new HashMap<String, Object>();
			//公共参数
			
			form.put("method", "virtualdelivergoods");// 处理方法
			Date date = new Date();
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			String timestamp = df.format(date);
			form.put("timestamp", timestamp);
			form.put("appkey", ConstInstance.getValuedByKeyd(CODE,"appKey"));
			form.put("v", "1.0");
			// 测试订单获取接口
			form.put("VendorId", ConstInstance.getValuedByKeyd(CODE,"vendorId"));// 供应商id
			form.put("OrderKindType", orderType);// 订单类型（5电子预付卡（零 售）,6 电子预付卡（企业贩买）,7 手机充值类,8 游戏 充值,9流量充值,10卡号入 库类,11 旅游12实物卡13 电子卡） 充
			form.put("RechargeAccount", userNumber);// 充值账户
			form.put("BeginDate", getDayStr(dateStart,Integer.valueOf(ConstInstance.getValuedByKeyd(CODE,"start_inv")),"00:00:00"));//昨天的时间  
			form.put("EndDate", getDayStr(dateStart,Integer.valueOf(ConstInstance.getValuedByKeyd(CODE,"end_inv")),"23:59:59"));// 明天的时间
			String key=ConstInstance.getValuedByKeyd(CODE,"appSecret");
			String signStr=(key+EncryptUtil.getOrderByLetter(form)+key).trim();
			String sign = EncryptUtil.SHA1(signStr, "UTF-8");	
			form.put("sign", sign);
			return form;

		}
	
	
	
	
}
